/*
 * $Id: $
 */
package org.rcgwt.client.ui.grid.renderer;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.rcgwt.client.theme.CssStyle;
import org.rcgwt.client.ui.grid.internal.model.IGridModel;
import org.rcgwt.client.ui.grid.internal.model.IHeaderModel;
import org.rcgwt.client.ui.grid.internal.model.ITitleCellModel;
import org.rcgwt.client.ui.grid.internal.model.ITitleRowModel;
import org.rcgwt.client.ui.grid.internal.model.IViewModel;
import org.rcgwt.client.ui.grid.internal.model.IViewModelElements;
import org.rcgwt.client.ui.grid.provider.IColumnProvider;
import org.rcgwt.client.ui.grid.theme.IGridTheme;

import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.TableSectionElement;

/**
 * 
 * @author Olivier Oeuillot (latest modification by $Author: $)
 * @version $Revision: $ $Date: $
 */
public class DefaultTitleRowRenderer extends AbstractRenderer<ITitleRowModel>
		implements ITitleRowRenderer {

	private static final String TITLE_ROW_CELL_PROPERTY = "_titleRowCell";

	public Element render(IViewRenderContext viewRenderContext,
			Element parentElement, ITitleRowModel titleRow, int renderedIndex) {

		assert parentElement instanceof TableSectionElement : "Invalid parent type ("
				+ parentElement + ")";

		Element rowElement;

		if (titleRow.isFocusable()) {
			Element focusableParent = createFocusableElement(parentElement
					.getOwnerDocument());
			rowElement = focusableParent;

			viewRenderContext.getGridRenderContext().getGridModel()
					.getGridWidget().getGridModelController()
					.installElementEventsListener(viewRenderContext, titleRow,
							focusableParent, null);

			CssStyle titleRowCssStyle = viewRenderContext
					.getGridRenderContext().getTheme()
					.getFocusedTitleRowCssStyle(titleRow);
			rowElement.setClassName(titleRowCssStyle.getClassName());

		} else {
			rowElement = parentElement.getOwnerDocument().createDivElement();
		}

		update(viewRenderContext, rowElement, titleRow, renderedIndex);

		return rowElement;
	}

	@Override
	protected CssStyle getCssStyle(IViewRenderContext renderContext,
			ITitleRowModel titleRow) {
		return renderContext.getGridRenderContext().getTheme()
				.getTitleRowCssStyle(titleRow);
	}

	@Override
	public void update(IViewRenderContext viewRenderContext,
			Element rowElement, ITitleRowModel titleRow, int renderedIndex) {
		super.update(viewRenderContext, rowElement, titleRow, renderedIndex);

		viewRenderContext.getViewModel().getViewModelElements()
				.setTitleRowElement(titleRow, rowElement, renderedIndex);
	}

	@SuppressWarnings("boxing")
	@Override
	protected void updateContent(IViewRenderContext viewRenderContext,
			Element titleRowElement, ITitleRowModel titleRowModel) {

		IViewModel viewModel = viewRenderContext.getViewModel();
		IGridModel gridModel = viewModel.getGridModel();
		IGridTheme theme = viewRenderContext.getGridRenderContext().getTheme();

		/*
		 * int headerHeight = theme.getHorizontalHeaderHeight(viewModel); if
		 * (headerHeight > 0) {
		 * rowElement.getStyle().setPropertyPx(Styles.HEIGHT, headerHeight); }
		 */

		if (titleRowModel.isFocusable()) {
			// titleRowElement = titleRowElement.getFirstChildElement();
		}

		int cellElementsCount = 0;
		NodeList<Node> children = null;
		if (titleRowElement.hasChildNodes()) {
			children = titleRowElement.getChildNodes();

			cellElementsCount = children.getLength();
		}

		IColumnProvider columnProvider = gridModel.getGridWidget()
				.getColumnProvider();

		Iterator<Integer> columnIterator = columnProvider
				.getColumnModelIndexes(titleRowModel.getModelIndex());

		ITitleCellModel titleCellModels[] = titleRowModel.listTitleCellModels();

		int titleCellIndex = 0;
		int renderedColumnIndex = 0;
		for (; columnIterator.hasNext(); renderedColumnIndex++) {
			int columnModelIndex = columnIterator.next();

			ITitleCellModel titleCell = titleCellModels[columnModelIndex];

			IRenderer<ITitleCellModel> titleCellRenderer = theme
					.getTitleCellRenderer(titleCell);

			Element titleCellElement = null;
			for (; titleCellIndex < cellElementsCount;) {
				Node node = children.getItem(titleCellIndex++);
				if (node.getNodeType() != Node.ELEMENT_NODE) {
					continue;
				}

				Element e = Element.as(node);

				if (e.getPropertyBoolean(TITLE_ROW_CELL_PROPERTY)) {
					titleCellElement = e;
					break;
				}
			}

			if (titleCellElement != null) {
				titleCellRenderer.update(viewRenderContext, titleCellElement,
						titleCell, renderedColumnIndex);

				continue;
			}

			titleCellElement = titleCellRenderer.render(viewRenderContext,
					titleRowElement, titleCell, renderedColumnIndex);

			titleCellElement.setPropertyBoolean(TITLE_ROW_CELL_PROPERTY, true);

			titleRowElement.appendChild(titleCellElement);
		}

	}

	@Override
	public void updateLayout(IViewRenderContext viewRenderContext,
			ITitleRowModel titleRowModel, Element element, int totalSize,
			int[] sizesByColumnModelIndex, int titleRowHeight) {

		IViewModel viewModel = viewRenderContext.getViewModel();
		IViewModelElements viewModelElements = viewModel.getViewModelElements();

		IGridTheme gridTheme = viewRenderContext.getGridRenderContext()
				.getTheme();

		Style style = element.getStyle();

		style.setPropertyPx(Styles.WIDTH, totalSize
				+ gridTheme.getMaximumVerticalScrollBarWidth());

		int margins[] = null;

		int titleCellRenderedIndex = 0;
		for (ITitleCellModel titleCellModel : titleRowModel
				.listTitleCellModels()) {

			Element titleCellElement = viewModelElements
					.getTitleCellElement(titleCellModel);
			if (element == null) {
				continue;
			}

			ITitleCellRenderer titleCellRenderer = gridTheme
					.getTitleCellRenderer(titleCellModel);

			int colspan = titleCellModel.getColumnModel().getColumn()
					.getTitleColSpan(titleRowModel.getModelIndex());
			if (colspan < 1) {
				colspan = 1;
			}

			int cellWidth = 0;
			for (int i = 0; i < colspan; i++) {
				cellWidth += sizesByColumnModelIndex[titleCellModel
						.getModelIndex()];
			}

			if (titleCellRenderedIndex == 0) {
				if (margins == null) {
					margins = gridTheme.getTableMargins();
				}
				cellWidth += margins[3];

			} else if (titleCellRenderedIndex == sizesByColumnModelIndex.length - 1) {
				if (margins == null) {
					margins = gridTheme.getTableMargins();
				}
				cellWidth += margins[1];
			}

			titleCellRenderer.updateLayout(viewRenderContext, titleCellModel,
					titleCellElement, cellWidth, titleRowHeight);

			titleCellRenderedIndex++;
		}
	}

	@Override
	public int getSize(IViewRenderContext viewRenderContext,
			ITitleRowModel titleRowModel, Element titleRowElement) {

		IGridTheme gridTheme = viewRenderContext.getGridRenderContext()
				.getTheme();

		IHeaderModel headerModel = titleRowModel.getHeader();

		if (headerModel.getOrientation() == IHeaderModel.Orientation.HORIZONTAL) {

			return gridTheme.getHorizontalHeaderHeight(headerModel);
		}

		return gridTheme.getVerticalHeaderWidth(headerModel);
	}

	@Override
	public void setFocus(IViewRenderContext viewRenderContext,
			ITitleRowModel titleRowModel, Element titleRowElement) {

		if (false) {
			Log
					.info("TitleRowRenderer: Set focus to '" + titleRowElement
							+ "'");
		}

		focusElement(titleRowElement);
	}

	@Override
	public ITitleCellModel getTitleCellModelByRenderedIndex(
			IViewRenderContext viewRenderContext, ITitleRowModel titleRowModel,
			Element titleRowElement, int titleCellRenderedIndex) {

		if (titleRowElement.hasChildNodes() == false) {
			return null;
		}

		Element element = titleRowElement.getFirstChildElement();

		int renderedIndex = 0;
		List<ITitleCellModel> list = null;
		if (titleCellRenderedIndex < 0) {
			list = new ArrayList<ITitleCellModel>();
		}

		for (; element != null; element = element.getNextSiblingElement()) {
			if (element.getPropertyBoolean(TITLE_ROW_CELL_PROPERTY) == false) {
				continue;
			}

			if (list == null && renderedIndex < titleCellRenderedIndex) {
				renderedIndex++;
				continue;
			}

			IViewModel viewModel = viewRenderContext.getViewModel();

			ITitleCellModel titleCellModel = (ITitleCellModel) viewModel
					.getViewModelElements()
					.findElementModel(viewModel, element);

			if (list == null) {
				return titleCellModel;
			}

			list.add(titleCellModel);
		}

		if (list == null || titleCellRenderedIndex >= 0) {
			return null;
		}

		int idx = list.size() + titleCellRenderedIndex;
		if (idx < 0) {
			idx = 0;
		}

		return list.get(idx);
	}

	@Override
	public int getTitleCellRenderedIndex(IViewRenderContext viewRenderContext,
			ITitleRowModel titleRowModel, Element titleRowElement,
			ITitleCellModel titleCellModel) {

		if (titleRowElement.hasChildNodes() == false) {
			return -1;
		}

		IViewModel viewModel = viewRenderContext.getViewModel();
		IViewModelElements viewModelElements = viewModel.getViewModelElements();

		Element titleCellElement = viewModelElements
				.getTitleCellElement(titleCellModel);
		if (titleCellElement == null) {
			return -1;
		}

		Element element = titleRowElement.getFirstChildElement();

		int renderedIndex = 0;

		for (; element != null; element = element.getNextSiblingElement()) {
			if (element.getPropertyBoolean(TITLE_ROW_CELL_PROPERTY) == false) {
				continue;
			}

			if (titleCellElement == element) {
				return renderedIndex;
			}

			renderedIndex++;
		}

		return -1;
	}

}
